/**
 * Copyright (C) 2009 aileron.cc
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package cc.aileron.wsgi.activity.registry;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cc.aileron.wsgi.activity.WsgiActivity;
import cc.aileron.wsgi.activity.WsgiProcess;

/**
 * @author Aileron
 */
public enum WsgiTransitionCategory
{
    /**
     * 404
     */
    NOT_FOUND
    {
        @SuppressWarnings("unchecked")
        @Override
        public <Resource> WsgiProcess<Resource> process(final String... value)
        {
            return notFound;
        }
    },

    /**
     * リダイレクト
     */
    REDIRECT
    {
        @Override
        public <Resource> WsgiProcess<Resource> process(final String... value)
        {
            if (value.length == 0)
            {
                throw new IllegalArgumentException();
            }
            final UriTemplate uriTemplate = new UriTemplate(value[0]);
            return new WsgiProcess<Resource>()
            {
                @Override
                public void doProcess(final WsgiActivity<Resource> activity)
                        throws Exception
                {
                    final String path = uriTemplate.replace(activity.resourceAccessor());
                    activity.context()
                            .response()
                            .sendRedirect(path);
                }

                @Override
                public String toString()
                {
                    return "redirect(" + uriTemplate + ")";
                }
            };
        }
    },

    /**
     * ローカルリダイレクト
     */
    LOCALREDIRECT
    {
        @Override
        public <Resource> WsgiProcess<Resource> process(final String... value)
        {
            if (value.length == 0)
            {
                throw new IllegalArgumentException();
            }
            final UriTemplate uriTemplate = new UriTemplate(value[0]);
            return new WsgiProcess<Resource>()
            {
                @Override
                public void doProcess(final WsgiActivity<Resource> activity)
                        throws Exception
                {
                    final String base = activity.context()
                            .request()
                            .getContextPath();
                    final String uri = uriTemplate.replace(activity.resourceAccessor());

                    logger.trace("LOCALREDIRECT path : {}{}", base, uri);

                    activity.context()
                            .response()
                            .sendRedirect(base + uri);
                }

                @Override
                public String toString()
                {
                    return "redirect(" + uriTemplate + ")";
                }
            };
        }
    },

    /**
     * フォワード
     */
    FORWARD
    {
        @Override
        public <Resource> WsgiProcess<Resource> process(final String... value)
        {
            if (value.length == 0)
            {
                throw new IllegalArgumentException();
            }
            final UriTemplate uriTemplate = new UriTemplate(value[0]);
            return new WsgiProcess<Resource>()
            {
                @Override
                public void doProcess(final WsgiActivity<Resource> activity)
                        throws Exception
                {
                    final HttpServletRequest request = activity.context()
                            .request();
                    final HttpServletResponse response = activity.context()
                            .response();
                    final ServletContext context = activity.context()
                            .application();
                    final String uri = uriTemplate.replace(activity.resourceAccessor());
                    final RequestDispatcher rd = context.getRequestDispatcher(uri);
                    rd.forward(request, response);
                }

                @Override
                public String toString()
                {
                    return "forward(" + uriTemplate + ")";
                }
            };
        }
    };

    /**
     * notFound
     */
    @SuppressWarnings("unchecked")
    static final WsgiProcess notFound = new WsgiProcess()
    {
        @Override
        public void doProcess(final WsgiActivity event) throws Exception
        {
            event.context()
                    .response()
                    .setStatus(404);
        }

        @Override
        public String toString()
        {
            return "notfound()";
        }
    };

    /**
     * @param <Resource>
     * @param value
     * @return process
     */
    public abstract <Resource> WsgiProcess<Resource> process(final String... value);

    /**
     * logger
     */
    final Logger logger = LoggerFactory.getLogger(this.getClass());
}